package cn.wolfcode.service.impl;

import cn.wolfcode.common.exception.BusinessException;
import cn.wolfcode.domain.AccountLog;
import cn.wolfcode.domain.AccountTransaction;
import cn.wolfcode.domain.OperateIntergralVo;
import cn.wolfcode.mapper.AccountLogMapper;
import cn.wolfcode.mapper.AccountTransactionMapper;
import cn.wolfcode.mapper.UsableIntegralMapper;
import cn.wolfcode.service.IUsableIntegralService;
import cn.wolfcode.web.msg.IntergralCodeMsg;
import com.alibaba.fastjson.JSON;
import io.seata.rm.tcc.api.BusinessActionContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;


@Service
@Slf4j
public class UsableIntegralServiceImpl implements IUsableIntegralService {
    @Autowired
    private UsableIntegralMapper usableIntegralMapper;
    @Autowired
    private AccountTransactionMapper accountTransactionMapper;
    @Autowired
    private AccountLogMapper accountLogMapper;

    @Override
    @Transactional
    public void decrIntergral(OperateIntergralVo operateIntergralVo) {
//        int a = 1/0;

        // 日志
        AccountLog accountLog = new AccountLog();
        accountLog.setAmount(operateIntergralVo.getValue());
        accountLog.setGmtTime(new Date());
        accountLog.setInfo(operateIntergralVo.getInfo());
        accountLog.setPkValue(operateIntergralVo.getPk());
        accountLog.setType(AccountLog.TYPE_DECR);
        accountLogMapper.insert(accountLog);

        // 减少用户积分
        int count = usableIntegralMapper.decrIntergral(operateIntergralVo.getUserId(), operateIntergralVo.getValue());
        if ( count == 0)
            throw new BusinessException(IntergralCodeMsg.INTERGRAL_NOT_ENOUGH);

    }

    @Override
    @Transactional
    public void incrIntergral(OperateIntergralVo operateIntergralVo) {
        // 日志
        AccountLog accountLog = new AccountLog();
        accountLog.setAmount(operateIntergralVo.getValue());
        accountLog.setGmtTime(new Date());
        accountLog.setInfo(operateIntergralVo.getInfo());
        accountLog.setPkValue(operateIntergralVo.getPk());
        accountLog.setType(AccountLog.TYPE_INCR);
        accountLogMapper.insert(accountLog);

        // 增加用户积分
        usableIntegralMapper.addIntergral(operateIntergralVo.getUserId(), operateIntergralVo.getValue());
    }

    @Override
    public void incrIntergralTry(OperateIntergralVo operateIntergralVo, BusinessActionContext context) {
        insertRecord(operateIntergralVo, context, AccountTransaction.STATE_TRY, AccountTransaction.INCR_TYPE);
    }

    private void insertRecord(OperateIntergralVo operateIntergralVo, BusinessActionContext context, int state, String type) {
        // t_account_transaction 表插入数据 (执行过try的证明)
        AccountTransaction accountTransaction = new AccountTransaction();
        accountTransaction.setUserId(operateIntergralVo.getUserId());
        accountTransaction.setTxId(context.getXid());
        accountTransaction.setActionId(String.valueOf(context.getBranchId()));
        accountTransaction.setAmount(operateIntergralVo.getValue());    // 变动积分
        accountTransaction.setGmtCreated(new Date());
        accountTransaction.setGmtModified(new Date());
        accountTransaction.setType(type);
        accountTransaction.setState(state);
        accountTransactionMapper.insert(accountTransaction);
    }

    @Override
    public void incrIntergralCommit(BusinessActionContext context) {
        AccountTransaction accountTransaction = accountTransactionMapper.get(context.getXid(), String.valueOf(context.getBranchId()));
        if (accountTransaction == null) {
            log.info("try未执行!");
            throw new BusinessException(IntergralCodeMsg.INTERGRAL_NOT_ENOUGH);
        }
        if (accountTransaction.getState() == AccountTransaction.STATE_TRY) {
            log.info("try已执行!");
            OperateIntergralVo operateIntergralVo = JSON.parseObject(context.getActionContext("operateIntergralVo").toString(), OperateIntergralVo.class);
            // 加积分
            usableIntegralMapper.addIntergral(operateIntergralVo.getUserId(), operateIntergralVo.getValue());

            // 修改状态 TRY->COMMIT
            accountTransactionMapper.updateAccountTransactionState(context.getXid(), String.valueOf(context.getBranchId()), AccountTransaction.STATE_COMMIT, AccountTransaction.STATE_TRY);
        } else if (accountTransaction.getState() == AccountTransaction.STATE_COMMIT) {
            // 解决幂等性问题, 啥也不做即可
        } else {
            log.info("状态异常, 既不是try, 又不是commit");
        }
    }

    @Override
    public void incrIntergralRollback(BusinessActionContext context) {
        log.info("进入cancel");
        AccountTransaction accountTransaction = accountTransactionMapper.get(context.getXid(), String.valueOf(context.getBranchId()));
        if (accountTransaction == null) {
            log.info("try未执行!");
            OperateIntergralVo operateIntergralVo = JSON.parseObject(context.getActionContext("operateIntergralVo").toString(), OperateIntergralVo.class);
            insertRecord(operateIntergralVo, context, AccountTransaction.STATE_CANCEL, AccountTransaction.DECR_TYPE);
            return;
        }
        // 根据状态判断当前已经执行过什么
        if (accountTransaction.getState() == AccountTransaction.STATE_TRY) {
            log.info("try已执行!");

            accountTransactionMapper.updateAccountTransactionState(context.getXid(), String.valueOf(context.getBranchId()), AccountTransaction.STATE_CANCEL, AccountTransaction.STATE_TRY);
        } else if (accountTransaction.getState() == AccountTransaction.STATE_CANCEL) {
            // 解决幂等性问题, 啥也不做即可
        } else {
            log.info("状态异常, 既不是try, 又不是cancel");
        }
    }

    @Override
    public void decrIntergralTry(OperateIntergralVo operateIntergralVo, BusinessActionContext context) {
        insertRecord(operateIntergralVo, context, AccountTransaction.STATE_TRY, AccountTransaction.INCR_TYPE);
    }

    @Override
    public void decrIntergralCommit(BusinessActionContext context) {
        AccountTransaction accountTransaction = accountTransactionMapper.get(context.getXid(), String.valueOf(context.getBranchId()));
        if (accountTransaction == null) {
            log.info("try未执行!");
            throw new BusinessException(IntergralCodeMsg.INTERGRAL_NOT_ENOUGH);
        }
        if (accountTransaction.getState() == AccountTransaction.STATE_TRY) {
            log.info("try已执行!");
            OperateIntergralVo operateIntergralVo = JSON.parseObject(context.getActionContext("operateIntergralVo").toString(), OperateIntergralVo.class);
            // 加积分
            usableIntegralMapper.decrIntergral(operateIntergralVo.getUserId(), operateIntergralVo.getValue());

            // 修改状态 TRY->COMMIT
            accountTransactionMapper.updateAccountTransactionState(context.getXid(), String.valueOf(context.getBranchId()), AccountTransaction.STATE_COMMIT, AccountTransaction.STATE_TRY);
        } else if (accountTransaction.getState() == AccountTransaction.STATE_COMMIT) {
            // 解决幂等性问题, 啥也不做即可
        } else {
            log.info("状态异常, 既不是try, 又不是commit");
        }
    }

    @Override
    public void decrIntergralRollback(BusinessActionContext context) {
        log.info("进入cancel");
        AccountTransaction accountTransaction = accountTransactionMapper.get(context.getXid(), String.valueOf(context.getBranchId()));
        if (accountTransaction == null) {
            log.info("try未执行!");
            OperateIntergralVo operateIntergralVo = JSON.parseObject(context.getActionContext("operateIntergralVo").toString(), OperateIntergralVo.class);
            insertRecord(operateIntergralVo, context, AccountTransaction.STATE_CANCEL, AccountTransaction.DECR_TYPE);
            return;
        }
        // 根据状态判断当前已经执行过什么
        if (accountTransaction.getState() == AccountTransaction.STATE_TRY) {
            log.info("try已执行!");

            accountTransactionMapper.updateAccountTransactionState(context.getXid(), String.valueOf(context.getBranchId()), AccountTransaction.STATE_CANCEL, AccountTransaction.STATE_TRY);
        } else if (accountTransaction.getState() == AccountTransaction.STATE_CANCEL) {
            // 解决幂等性问题, 啥也不做即可
        } else {
            log.info("状态异常, 既不是try, 又不是cancel");
        }

    }


}
